package ast.stmt;

import icg.EQIdent;
import icg.EQLabel;
import icg.EQLiteral;
import icg.EQTemp;
import icg.Quadruple;

import java.util.Vector;

import ts.FunInfo;
import ts.SymbolTable;

import ast.Node;
import ast.exp.Expression;
import ast.type.OpType;
import ast.type.Type;

public class ProcStmt extends Statement {
	private Integer id;
	private Vector<Expression> listParReal;
	private EQTemp addr;
	private EQLabel falseL;
	private EQLabel trueL;
	public ProcStmt(Integer id, Vector<Expression> listParReal) {
		this.id = id;
		this.listParReal = listParReal;
	}

	@Override
	public String toString() {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < listParReal.size(); i++) {
			sb.append(listParReal.elementAt(i).toString()).append("\n");
		}
		return "<ProcStmt id=\"" + id + "\">\n" + "<listParReal>\n"
				+ sb.toString() + "</listParReal>\n" + "</ProcStmt>";
	}

	public Integer getId() {
		return id;
	}

	@Override
	public void typeCheck(Type type) {
		FunInfo fi = (FunInfo) Node.st.getInfo(id);

		if (fi.getListPar().size() != listParReal.size()) {
			System.out.println("the number of real and formal params are differents");
			SymbolTable.errors++;
		}

		for (int i = 0; i < listParReal.size(); i++) {
			Type typeParReal = listParReal.elementAt(i).typeCheck();
			if (i < fi.getListPar().size())
				if (Node.st.getInfo(fi.getListPar().elementAt(i)).getType() != typeParReal) {
					System.out.println("the type of param " + i
							+ " are differents " + typeParReal);
					SymbolTable.errors++;
				}
		}
	}

	@Override
	public void genCode() {
		for (Expression d: listParReal) {
			if (d.getType()==Type.BOOLEAN) { //Parametro booleano
				EQLabel l1 = new EQLabel();
				EQLabel l2 = new EQLabel();
				d.trueL = l1;
				d.falseL = EQLabel.FALL;
				d.genCode();
				Node.icg.gen(Quadruple.param(new EQLiteral("0")));
				Node.icg.gen(Quadruple.jump(l2));
				EQLabel.useLabel(l1);
				Node.icg.gen(Quadruple.param(new EQLiteral("1")));
				EQLabel.useLabel(l2);
			} else { //Parametro nao booleano
				d.genCode();
				Node.icg.gen(Quadruple.param(d.addr));
			}
		}
		
		if (Node.st.getInfo(id).getType()==Type.VOID) { //Procedimento
			Node.icg.gen(Quadruple.procCall(new EQIdent(id.toString()), new EQLiteral(listParReal.size()+"")));
		} else if (Node.st.getInfo(id).getType()==Type.BOOLEAN) { //Funcao Booleana
			EQTemp t = new EQTemp();
			Node.icg.gen(Quadruple.funcCall(t, new EQIdent(id.toString()), new EQLiteral(listParReal.size()+"")));
			if (this.trueL.equals(EQLabel.FALL)) {
				Node.icg.gen(Quadruple.branch(OpType.IGUAL, falseL, t, new EQLiteral("0")));
			} else if (this.falseL.equals(EQLabel.FALL)) {
				Node.icg.gen(Quadruple.branch(OpType.DIFERENTE, trueL, t, new EQLiteral("0")));
			} else {
				Node.icg.gen(Quadruple.branch(OpType.DIFERENTE, trueL, t, new EQLiteral("0")));
				Node.icg.gen(Quadruple.jump(this.falseL));
			}
		} else { //Funcao nao booleana
			addr = new EQTemp();
			Node.icg.gen(Quadruple.funcCall(addr, new EQIdent(id.toString()), new EQLiteral(listParReal.size()+"")));
		}
	}

	public EQLabel getFalseL() {
		return falseL;
	}

	public void setFalseL(EQLabel falseL) {
		this.falseL = falseL;
	}

	public EQLabel getTrueL() {
		return trueL;
	}

	public void setTrueL(EQLabel trueL) {
		this.trueL = trueL;
	}

	public Vector<Expression> getListParReal() {
		return listParReal;
	}

	public void setListParReal(Vector<Expression> listParReal) {
		this.listParReal = listParReal;
	}
}
